#ifndef Cc
#define Cc
#include <algorithm>
#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

class QueryResult;
class TextQuery {
public:
  using LineNo = vector<string>::size_type;
  TextQuery(ifstream &);
  QueryResult query(const string &) const;

private:
  shared_ptr<vector<string>> input;
  map<string, shared_ptr<set<LineNo>>> result;
};

class QueryResult {
public:
  friend ostream &print(ostream &, const QueryResult &);

public:
  QueryResult(const string &s, shared_ptr<set<TextQuery::LineNo>> set,
              shared_ptr<vector<string>> v)
      : word(s), nos(set), input(v) {}

private:
  string word;
  shared_ptr<std::set<TextQuery::LineNo>> nos;
  shared_ptr<vector<string>> input;
};

ostream &print(ostream &, const QueryResult &);

TextQuery::TextQuery(ifstream &ifs) : input(new vector<string>) {
  LineNo lineNo{0};
  for (string line; getline(ifs, line); ++lineNo) {
    input->push_back(line);
    istringstream line_stream(line);
    string word;
    while (line_stream >> word) {
      /* code */
      auto &nos = result[word];
      if (!nos)
        nos.reset(new set<LineNo>);
      nos->insert(lineNo);
    }
  }
}

QueryResult TextQuery::query(const string &str) const {
  // use static just allocate once.
  static shared_ptr<set<LineNo>> nodate(new set<LineNo>);
  auto found = result.find(str);
  if (found == result.end())
    return QueryResult(str, nodate, input);
  else
    return QueryResult(str, found->second, input);
}

ostream &print(std::ostream &out, const QueryResult &qr) {
  out << qr.word << " occurs " << qr.nos->size()
      << (qr.nos->size() > 1 ? " times" : " time") << std::endl;
  for (auto i : *qr.nos)
    out << "\t(line " << i + 1 << ") " << qr.input->at(i) << std::endl;
  return out;
}
#endif //只要简单的加上就好了，无视C++中的作用域规则,作用是防止头文件被重复包含